package com.polaris.live.ui.login.verify

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.view.KeyEvent
import android.view.View
import android.view.animation.DecelerateInterpolator
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import com.blankj.utilcode.util.ColorUtils
import com.blankj.utilcode.util.SpanUtils
import com.blankj.utilcode.util.StringUtils
import com.polaris.live.R
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.constant.BizEventConst
import com.polaris.live.common.event.EventMessage
import com.polaris.live.common.ext.dp
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.network.parseState
import com.polaris.live.common.util.ImmersionBarBuilder
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.common.util.SoftKeyBoardHelper
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.databinding.ActivitySetPasswordBinding
import com.polaris.live.dialog.GlobalDialogManager
import com.polaris.live.interface_bag.TextWatcherAdapter
import com.polaris.live.translation.R.string
import com.polaris.live.ui.login.BaseGoogleLoginActivity
import com.polaris.live.ui.main.activity.MainActivity
import com.polaris.live.utils.CommonUtils
import com.polaris.live.utils.UserUtils
import com.polaris.live.utils.getBooleanOrString
import com.polaris.live.viewmodel.VerifyViewModel
import org.greenrobot.eventbus.EventBus

/**
 * 设置/忘记 密码页
 *
 * @author Created by 半仙 on 2023/8/24/024 15:41
 */
class SetPasswordActivity : BaseGoogleLoginActivity<VerifyViewModel, ActivitySetPasswordBinding>() {

    private var mAreaCode: String? = null
    private var mPhoneNumber: String? = null
    private var mGmail: String? = null
    private var mGoogleValidate: String? = null

    private var mIsLogin = true//是否是登录页面
    private var mIsFirstSet = true//是否首次设置密码

    private var mIsShowLook = false // 判断密码是否可见
    private var mIsPopupBoard = false //判断是否弹出软件盘了

    private var mIsSentCode = false //是否发送过验证码
    private var mIsTiming = false // 判断 定时器是否在在跑

    //从哪个页面来的
    private val mIsSettingCome by lazy {
        intent.getBooleanOrString("isSettingCome", false)
    }

    override fun ImmersionBarBuilder.buildImmersionBar() {
        setTitleBar(mBinding.llSetTitle)
    }

    override fun initView(savedInstanceState: Bundle?) {
        super.initView(savedInstanceState)

        initView()
        initListener()
        initObserver()
    }

    private fun initView() {
        mIsLogin = intent.getBooleanOrString("isLogin", true)
        mIsFirstSet = intent.getBooleanOrString("isFirstSet", true)
        mAreaCode = intent.getStringExtra("areaCode")
        mPhoneNumber = intent.getStringExtra("phoneNumber")
        mGmail = intent.getStringExtra("gmail")
        mGoogleValidate = intent.getStringExtra("googleValidate")

        mBinding.passwordNumber.text = resolveCurrentNumber()

        if (mIsFirstSet) {//首次设置密码
            mBinding.passwordTitle.text = StringUtils.getString(string.set_password)
            mBinding.passwordDetail.text = StringUtils.getString(string.enter_password)
            mBinding.icTitle.text = StringUtils.getString(string.enter_password)
        } else {//重新设置密码
            mBinding.passwordTitle.text = StringUtils.getString(string.set_new_password)
            mBinding.passwordDetail.text = StringUtils.getString(string.enter_new_password)
            mBinding.icTitle.text = StringUtils.getString(string.enter_new_password)
        }

        mBinding.verifyTime.text = SpanUtils.with(mBinding.verifyTime)
            .append(StringUtils.getString(string.verify_again))
            .setForegroundColor(ColorUtils.getColor(R.color.loginTitleTextColor))
            .setUnderline()
            .create()

        //设置密码
        passwordSet()

        //软键盘
        keyboard()

        //验证码
        verifyEdit()

        //非从设置来的，直接发送验证码
        val timeInMillis = CacheUtil.isSentVerifyCode(resolveCurrentNumber(), getSendType())
        if (!mIsSettingCome || timeInMillis > 0) {
            sendVerifyCode(timeInMillis)
        }
    }

    private fun initListener() {
        mBinding.verifyTime.setOnSingleClickListener {
            if (!mIsTiming) {
                sendVerifyCode()
            }
        }

        mBinding.icBack.setOnSingleClickListener {
            finish()
        }

        mBinding.goLogin.setOnSingleClickListener {
            val areaCode = mAreaCode
            val phoneNumber = mPhoneNumber
            val gmail = mGmail

            if (gmail.isNullOrEmpty() && (areaCode.isNullOrEmpty() || phoneNumber.isNullOrEmpty())) {
                ToastGravity.showGravity(string.error_data)
                return@setOnSingleClickListener
            }

            if (mBinding.goLogin.alpha == 1.0f) {
                val pwd = mBinding.passwordEdit.text?.toString()
                val verifyCode = getVerifyCode()

                if (pwd.isNullOrBlank()) {
                    ToastGravity.showGravity(string.password_empty)
                    return@setOnSingleClickListener
                } else if (pwd.length < 6) {
                    ToastGravity.showGravity(string.password_min_limit)
                    return@setOnSingleClickListener
                }

                if (verifyCode.isNullOrBlank()) {
                    ToastGravity.showGravity(string.verify_code_error)
                    return@setOnSingleClickListener
                }
                if (!mIsLogin) {
                    mViewModel.changePwd(isGmailLogin(), pwd, verifyCode)
                } else {
                    if (!gmail.isNullOrEmpty()) {
                        mViewModel.loginGmailByPassword(
                            gmail,
                            pwd,
                            AppConst.UserPwdType.FIND_PASSWORD,
                            verifyCode
                        )
                    } else if (!areaCode.isNullOrEmpty() && !phoneNumber.isNullOrEmpty()) {
                        mViewModel.loginPhoneByPassword(
                            areaCode,
                            phoneNumber,
                            pwd,
                            AppConst.UserPwdType.FIND_PASSWORD,
                            verifyCode
                        )
                    }
                }
            }
        }
    }

    private fun initObserver() {
        mViewModel.countdownLiveData.observe(this) { millisUntilFinished ->
            if (millisUntilFinished == 0L) {
                mIsTiming = false
                mBinding.verifyTime.text = SpanUtils.with(mBinding.verifyTime)
                    .append(StringUtils.getString(string.verify_again))
                    .setUnderline()
                    .setForegroundColor(ColorUtils.getColor(R.color.loginTitleTextColor))
                    .create()
            } else {
                mIsTiming = true
                val nowTime = millisUntilFinished / 1000
                mBinding.verifyTime.text = "${StringUtils.getString(string.verify_again)}(${nowTime}s)"
            }
        }

        mViewModel.verifyLiveData.observe(this) { resultState ->
            parseState(resultState, {
                mViewModel.countdown()

                checkListenerInput()

                CacheUtil.saveVerifyCode(resolveCurrentNumber(), getSendType())
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
        mViewModel.loginPwsRespLiveData.observe(this) { resultState ->
            parseState(resultState, {
                CacheUtil.deleteVerifyCode(resolveCurrentNumber(), getSendType())

                //登录成功
                saveSuccessPhoneNumber()
                UserUtils.loginSuccess(it)

                startActivity(Intent(this, MainActivity::class.java))
                setResult(RESULT_OK)
                finish()
            }, {
                if (it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT || it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT_LOGIN || it.errCode == CommonConst.ErrorCode.SEAL_ACCOUNT_STOP) {
                    GlobalDialogManager.showSealAccountDialog(this, JsonUtils.toJson(it.ext))
                } else {
                    ToastGravity.showGravity(it.errorMsg)
                }
            })
        }
        mViewModel.changePwdLiveData.observe(this) { resultState ->
            parseState(resultState, {
                CacheUtil.deleteVerifyCode(resolveCurrentNumber(), getSendType())

                EventBus.getDefault().post(EventMessage(BizEventConst.INFO_UPDATA))
                finish()
            }, {
                ToastGravity.showGravity(it.errorMsg)
            })
        }
    }

    private fun getVerifyCode(): String? {
        val etCodeOne = mBinding.etNumberOne.text?.toString()
        val etCodeTwo = mBinding.etNumberTwo.text?.toString()
        val etCodeThree = mBinding.etNumberThree.text?.toString()
        val etCodeFour = mBinding.etNumberFour.text?.toString()

        return if (etCodeOne.isNullOrBlank() || etCodeTwo.isNullOrBlank() || etCodeThree.isNullOrBlank() || etCodeFour.isNullOrBlank()) {
            null
        } else {
            "$etCodeOne$etCodeTwo$etCodeThree$etCodeFour"
        }
    }

    private fun checkAndToLogin() {
        val areaCode = mAreaCode
        val phoneNumber = mPhoneNumber
        val gmail = mGmail
        val pwd = mBinding.passwordEdit.text?.toString()
        val verifyCode = getVerifyCode()

        if (mIsSentCode && !pwd.isNullOrBlank() && pwd.length >= 6 && !verifyCode.isNullOrBlank()) {
            if (!gmail.isNullOrEmpty()) {
                if (!mIsLogin) {
                    mViewModel.changePwd(isGmailLogin(), pwd, verifyCode)
                } else {
                    mViewModel.loginGmailByPassword(
                        gmail,
                        pwd,
                        AppConst.UserPwdType.FIND_PASSWORD,
                        verifyCode
                    )
                }
            } else if (!areaCode.isNullOrBlank() && !phoneNumber.isNullOrBlank()) {
                if (!mIsLogin) {
                    mViewModel.changePwd(isGmailLogin(), pwd, verifyCode)
                } else {
                    mViewModel.loginPhoneByPassword(
                        areaCode,
                        phoneNumber,
                        pwd,
                        AppConst.UserPwdType.FIND_PASSWORD,
                        verifyCode
                    )
                }
            }
        }
    }

    private fun sendVerifyCode(timeInMillis: Long? = null) {
        mIsSentCode = true

        if (timeInMillis != null && timeInMillis > 0) {
            mViewModel.countdown(timeInMillis)
            return
        }

        val sendType = getSendType()

        val gmail = mGmail
        if (!gmail.isNullOrEmpty()) {
            if (mGoogleValidate != null) {
                mViewModel.sendGmailVerify(timeInMillis != null, gmail, mGoogleValidate, sendType)
                mGoogleValidate = null
            } else {
                verifyGoogle {
                    mViewModel.sendGmailVerify(timeInMillis != null, gmail, it, sendType)
                }
            }
        } else {
            val areaCode = mAreaCode
            val phoneNumber = mPhoneNumber
            if (!areaCode.isNullOrEmpty() && !phoneNumber.isNullOrEmpty()) {
                if (mGoogleValidate != null) {
                    mViewModel.sendPhoneVerify(timeInMillis != null, areaCode, phoneNumber, mGoogleValidate, sendType)
                    mGoogleValidate = null
                } else {
                    verifyGoogle {
                        mViewModel.sendPhoneVerify(timeInMillis != null, areaCode, phoneNumber, it, sendType)
                    }
                }
            }
        }
    }

    private fun resolveCurrentNumber(): String {
        val gmail = mGmail
        return if (!gmail.isNullOrEmpty()) {
            CommonUtils.resolveGmail(gmail) ?: ""
        } else {
            "+$mAreaCode $mPhoneNumber"
        }
    }

    private fun getSendType(): Int {
        return if (UserManager.getUser().userId == null) {
            AppConst.LoginType.BACK//找回密码(没登录用找回密码)
        } else {
            AppConst.LoginType.REVISE//修改密码(登录后用修改密码)
        }
    }

    private fun isGmailLogin(): Boolean {
        return !mGmail.isNullOrEmpty()
    }

    private fun saveSuccessPhoneNumber() {
        val areaCode = mAreaCode
        val phoneNumber = mPhoneNumber
        if (areaCode != null && phoneNumber != null) {
            CacheUtil.saveLastAreaCodeAndPhoneNumber(areaCode, phoneNumber)
        }
        val gmail = mGmail
        if (gmail != null) {
            CacheUtil.saveLastGmail(gmail)
        }
    }

    /**
     * 监听 验证码和密码是否输入好了  如果输入好了就吧 登录按钮开放
     */
    private fun checkListenerInput() {
        val verifyCode = getVerifyCode()

        val password =
            mBinding.passwordEdit.text.toString().replace("\\s+".toRegex(), "")  // 去掉所有空格

        if (mIsSentCode && !verifyCode.isNullOrBlank() && (password.length in 6..20)) {
            mBinding.goLogin.alpha = 1.0f
        } else {
            mBinding.goLogin.alpha = AppConst.NOTCLICK
        }
    }

    private fun verifyEdit() {
        mBinding.etNumberOne.inputType = EditorInfo.TYPE_CLASS_NUMBER
        mBinding.etNumberTwo.inputType = EditorInfo.TYPE_CLASS_NUMBER
        mBinding.etNumberThree.inputType = EditorInfo.TYPE_CLASS_NUMBER
        mBinding.etNumberFour.inputType = EditorInfo.TYPE_CLASS_NUMBER
        mBinding.etNumberOne.isFocusableInTouchMode = true
        mBinding.etNumberTwo.isFocusableInTouchMode = true
        mBinding.etNumberThree.isFocusableInTouchMode = true
        mBinding.etNumberFour.isFocusableInTouchMode = true

        setEditTextInputSpace(mBinding.passwordEdit)

        //addTextChangedListener设置监听文本变化，有输入跳转到下一个输入框
        mBinding.etNumberOne.addTextChangedListener(
            TextChangeLister(
                mBinding.etNumberOne,
                mBinding.etNumberTwo
            )
        )
        //setOnKeyListener设置监听键盘删除操作，删除完之后跳转到上一个输入框
        mBinding.etNumberTwo.setOnKeyListener(
            MyOnKeyListener(
                mBinding.etNumberOne,
                mBinding.etNumberTwo
            )
        )
        mBinding.etNumberTwo.addTextChangedListener(
            TextChangeLister(
                mBinding.etNumberTwo,
                mBinding.etNumberThree
            )
        )
        mBinding.etNumberThree.setOnKeyListener(
            MyOnKeyListener(
                mBinding.etNumberTwo,
                mBinding.etNumberThree
            )
        )
        mBinding.etNumberThree.addTextChangedListener(
            TextChangeLister(
                mBinding.etNumberThree,
                mBinding.etNumberFour
            )
        )
        mBinding.etNumberFour.setOnKeyListener(
            MyOnKeyListener(
                mBinding.etNumberThree,
                mBinding.etNumberFour
            )
        )

        mBinding.etNumberFour.addTextChangedListener(object : TextWatcherAdapter() {
            override fun afterTextChanged(s: Editable?) {
                mBinding.etNumberOne.setBackgroundResource(R.drawable.verify_edit_common_back)
                mBinding.etNumberTwo.setBackgroundResource(R.drawable.verify_edit_common_back)
                mBinding.etNumberThree.setBackgroundResource(R.drawable.verify_edit_common_back)
                mBinding.etNumberFour.setBackgroundResource(R.drawable.verify_edit_common_back)

                mBinding.etNumberOne.setTextColor(ColorUtils.getColor(R.color.f202028))
                mBinding.etNumberTwo.setTextColor(ColorUtils.getColor(R.color.f202028))
                mBinding.etNumberThree.setTextColor(ColorUtils.getColor(R.color.f202028))
                mBinding.etNumberFour.setTextColor(ColorUtils.getColor(R.color.f202028))

                val s4 = mBinding.etNumberFour.text?.toString()
                if (!s4.isNullOrBlank()) {
                    checkAndToLogin()
                }
                checkListenerInput()

            }
        })
    }

    private fun keyboard() {
        SoftKeyBoardHelper.setListener(this, object : SoftKeyBoardHelper.OnSoftKeyboardChangeListener {
            override fun keyBoardShow() {
                if (!mIsPopupBoard) {
                    val initialTranslationY = 0F
                    val finalTranslationY = -112.dp.toFloat() //-330f

                    val animator = ValueAnimator.ofFloat(initialTranslationY, finalTranslationY)
                    animator.duration = 350 // 设置动画的持续时间，单位为毫秒
                    animator.interpolator = DecelerateInterpolator()

                    animator.addUpdateListener { animation ->
                        val translationY = animation.animatedValue as Float
                        mBinding.llPhone.translationY = translationY
                        mBinding.llTitle.alpha = 1 - animation.animatedFraction
                        mBinding.icTitle.alpha = animation.animatedFraction
                    }

                    animator.addListener(object : AnimatorListenerAdapter() {
                        override fun onAnimationEnd(animation: Animator) {
                            mBinding.llTitle.alpha = 0f
                            mBinding.icTitle.alpha = 1f
                            mIsPopupBoard = true
                        }
                    })
                    animator.start()

                }
            }

            override fun keyBoardHide() {
                if (mIsPopupBoard) {
                    val initialTranslationY = -112.dp.toFloat()
                    val finalTranslationY = 0F

                    val animator = ValueAnimator.ofFloat(initialTranslationY, finalTranslationY)
                    animator.duration = 350 // 设置动画的持续时间，单位为毫秒
                    animator.interpolator = DecelerateInterpolator()

                    animator.addUpdateListener { animation ->
                        val translationY = animation.animatedValue as Float
                        mBinding.llPhone.translationY = translationY
                        mBinding.llTitle.alpha = animation.animatedFraction
                        mBinding.icTitle.alpha = 1 - animation.animatedFraction
                    }
                    animator.addListener(object : AnimatorListenerAdapter() {
                        override fun onAnimationEnd(animation: Animator) {
                            mBinding.llTitle.alpha = 1f
                            mBinding.icTitle.alpha = 0f
                            mIsPopupBoard = false
                        }
                    })
                    animator.start()
                }
            }
        })
    }

    private fun passwordSet() {
        mBinding.passwordEdit.inputType =
            InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD

        mBinding.passwordEdit.addTextChangedListener(object : TextWatcherAdapter() {
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                val toString = s?.toString()
                val trimmedStr = toString?.replace("\\s+".toRegex(), "")  // 去掉所有空格
                val size = trimmedStr?.length ?: 0

                if (size < 6) {
                    mBinding.passwordDangerous.visibility = View.VISIBLE
                } else {
                    mBinding.passwordDangerous.visibility = View.GONE
                }

                checkListenerInput()
            }
        })

        mBinding.passwordVisible.setOnClickListener {
            if (mIsShowLook) {
                mIsShowLook = false
                // 设置为不可见密码模式
                mBinding.passwordEdit.transformationMethod = PasswordTransformationMethod.getInstance()
                mBinding.passwordVisible.setImageResource(R.drawable.not_visible)

            } else {
                mIsShowLook = true
                // 设置为可见密码模式
                mBinding.passwordEdit.transformationMethod = HideReturnsTransformationMethod.getInstance()
                mBinding.passwordVisible.setImageResource(R.drawable.ok_visible)
            }
            val size = mBinding.passwordEdit.text.length
            mBinding.passwordEdit.setSelection(size)
        }
    }

    /**
     * 禁止EditText输入空格和换行符
     *
     * @param editText EditText输入框
     */
    private fun setEditTextInputSpace(editText: EditText) {
        val filter = InputFilter { source, start, end, dest, dstart, dend ->
            if (source == " "
                || source.toString().contentEquals("\n")
                || mBinding.passwordEdit.text.length == 20
            ) {
                ""
            } else {
                null
            }
        }
        editText.filters = arrayOf(filter)
    }

    private fun setInputBack() {
        if (mBinding.etNumberOne.hasFocus()) {
            mBinding.etNumberOne.setBackgroundResource(R.drawable.verify_edit_input_back)
        }
        if (mBinding.etNumberTwo.hasFocus()) {
            mBinding.etNumberTwo.setBackgroundResource(R.drawable.verify_edit_input_back)
        }
        if (mBinding.etNumberThree.hasFocus()) {
            mBinding.etNumberThree.setBackgroundResource(R.drawable.verify_edit_input_back)
        }
        if (mBinding.etNumberFour.hasFocus()) {
            mBinding.etNumberFour.setBackgroundResource(R.drawable.verify_edit_input_back)
        }
    }

    //自定义文本变化监听类
    private inner class TextChangeLister(
        private val thisEt: EditText?,
        private val newEt: EditText?,
    ) : TextWatcherAdapter() {

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
            if (before == 0 && count == 1) {
                thisEt?.clearFocus()
                newEt?.requestFocus()
            }
        }

        override fun afterTextChanged(s: Editable?) {
            val s4 = mBinding.etNumberFour.text?.toString()
            if (!s4.isNullOrBlank()) {
                checkAndToLogin()
            }

            checkListenerInput()
        }
    }

    //自定义键盘监听
    private inner class MyOnKeyListener(
        private val upDt: EditText?,
        private val thisDt: EditText?,
    ) : View.OnKeyListener {

        override fun onKey(view: View, i: Int, keyEvent: KeyEvent): Boolean {
            if (keyEvent.action == KeyEvent.ACTION_DOWN && i == KeyEvent.KEYCODE_DEL) {  //如果上一个输入框不为空
                if (upDt != null && thisDt?.text.toString().isEmpty()) {
                    upDt.isFocusable = true
                    upDt.isFocusableInTouchMode = true
                    upDt.requestFocus()
                    upDt.setText("")
                }
                return false
            }
            return false
        }
    }
}